require "Common/define"
require "Logic/Config"
require "Common/functions"
---@class TaskManager
TaskManager = {};
local this = TaskManager;
local taskTableData;
local taskBoxTableData;
local taskRemarkNowTableData = {};

local taskServerData = {};
local taskLivenessServerData = {};
local taskLivenessBoxServerData = {};


function TaskManager.init()
    taskTableData = G.dataTable["t_task"];
    taskBoxTableData = G.dataTable["t_taskbox"];
    this.condition = {};
    this.taskBoxTableDataByType = {};
    this.taskTableDataByType = {};
    this.taskServerDataByType = {};
    this.taskAllExpCountByType = {};
    this.taskTableDataByRemark = {};
    this.taskReceivedByRemark = {};
    taskLivenessServerData = {}
    taskLivenessServerData = {}
    this.unlockData={}
    this.unlockStoryData={}
    this.initUnlockData()
end
---------------------------------处理服务器数据----------开始-------------
---
function TaskManager.updataAllTaskServerData(serverData)
    for i = 1, #serverData do
        this.updataOneServerTaskData(serverData[i]);
    end
end

function TaskManager.updataOneServerTaskData(singletask)
    local data = this.getTaskServerData(singletask.taskId or singletask);
    data = {};
    data["taskId"] = singletask.taskId;
    local progress = tonumber(tostring(singletask.progress))
    data["progress"] = progress;
    if(singletask.reward == 1)then
        singletask.reward = -1
    end
    data["status"] = singletask.reward;
    local tempTaskConfig = this.getTaskTableData(singletask.taskId);
    if next(tempTaskConfig) ~= nil then
        if tempTaskConfig.f_PreTaskId ~= 0 then
            taskServerData[tostring(tempTaskConfig.f_PreTaskId)] = nil;
        end
        data["order"] = tempTaskConfig.f_Order;
        if singletask.reward ~= -1 then
            local flag = false;
            if tempTaskConfig.f_JudgmentMethod == 2 then
                if progress > tempTaskConfig.f_Progress then
                    flag = true;
                end
            elseif tempTaskConfig.f_JudgmentMethod == 3 then
                if progress > 0 and progress <= tempTaskConfig.f_Progress then
                    flag = true;
                end
            elseif tempTaskConfig.f_JudgmentMethod == 4 then
                if progress > 0 and progress < tempTaskConfig.f_Progress then
                    flag = true;
                end
            else
                if progress >= tempTaskConfig.f_Progress then
                    flag = true;
                end
            end
            if flag then
                data["progress"] = tempTaskConfig.f_Progress;
                data["status"] = 1
                local _taskDic = {}
                _taskDic.task_id = tostring(singletask.taskId)
                _taskDic.function_type = tempTaskConfig.f_FunctionType
                TAManager.TrackByDictionary("task_finish",_taskDic)
            end
        else
            this.addOneReceivedByRemark(tempTaskConfig);
        end
        local flag = this.conditionAndJudge(decodeJsonStrToTabel(tempTaskConfig.f_Condition));
        if not flag then
            data["status"]= -0.5;
        end
    else
        logError("找不到该任务t_task id:"..tostring(singletask.taskId))
    end
    -- if data["status"] and data["status"] ~= 1 then
    --     local _taskDic= {}
    --     _taskDic.task_id = tostring(data["taskId"])
    --     _taskDic.progress =  data["progress"] or 0
    --     _taskDic.function_type = tempTaskConfig.f_FunctionType
    --     TAManager.TrackByDictionary("task_get",_taskDic)
    -- end
    taskServerData[tostring(data.taskId)] = data;
end

function TaskManager.updataAllTaskLivenessServerData(serverData)
    for i = 1, #serverData do
        this.updataOneTaskLivenessServerData(serverData[i].livenessId, serverData[i].liveness);
    end
end

function TaskManager.updataOneTaskLivenessServerData(livenessId, liveness)
    local data = this.getTaskLivenessServerData(livenessId);
    data["livenessId"] = livenessId;
    data["liveness"] = int64ToNumber(liveness);
end

function TaskManager.updataAllTaskLivenessBoxServerData(serverData)
    for i = 1, #serverData do
        this.updataOneTaskLivenessBoxServerData(serverData[i]);
    end
end

function TaskManager.updataOneTaskLivenessBoxServerData(singletask)
    local data = this.getTaskLivenessBoxServerData(singletask.livenessBoxId);
    data["livenessBoxId"] = singletask.livenessBoxId;
    if(singletask.reward == 1)then
        singletask.reward = -1
    end
    data["reward"] = singletask.reward;
    local tempTaskConfig = this.getTaskBoxTableData(singletask.livenessBoxId);
    if next(tempTaskConfig) ~= nil then
        if singletask.reward ~= -1 then
            if this.getTaskLivenessServerData(tempTaskConfig.f_NeedExpType).liveness >= tempTaskConfig.f_NeedExpCount then
                data["reward"] = 1
            end
        end
    else
        logError("找不到该任务宝箱t_taskbox id:"..tostring(singletask.livenessBoxId))
    end
end
---
function TaskManager.updateGetRewardsServerTaskData(msg,isShow)
    local taskId
    if type(msg) == "number" then
        taskId =  msg
    else
        taskId = msg.taskId
    end
    local taskCg = this.getTaskTableData(taskId );
    local taskData = this.getTaskServerData(taskId );
    if taskCg == nil then
        logError("找不到该任务t_task id:"..tostring(taskId ))
        UISysTips.AddMsg("领取奖励失败!")
    end
    log("领取任务t_task id:"..tostring(taskId ))
    taskData["status"] = -1;
    this.addOneReceivedByRemark(taskCg);
    -- 更新成就点
    local tempLiveness = this.getTaskLivenessServerData(taskCg.f_ExpType)["liveness"];
    tempLiveness = tempLiveness + taskCg.f_ExpCount
    local boxTable
    local severData
    this.updataOneTaskLivenessServerData(taskCg.f_ExpType, tempLiveness);
        boxTable = this.getTaskBoxByType(taskCg.f_ExpType);
        for k, v in pairs(boxTable) do
            severData = this.getTaskLivenessBoxServerData(v.f_BoxID);
            if severData.reward == 0 and v.f_NeedExpCount <= tempLiveness then
                severData.reward = 1;
            end
        end
   -- end
    this.showTaskRewardByIdFromTable(taskId,isShow);

    --奖励领取后
    local _awardDic = {}
    _awardDic.task_id = tostring(taskId)
    _awardDic.function_type = taskCg.f_FunctionType
    _awardDic.task_exp_type = taskCg.f_ExpType
    _awardDic.task_exp_count = taskCg.f_ExpCount
    TAManager.TrackByDictionary("award_get",_awardDic)
end
---
function TaskManager.updateGetLivenessRewardsServerTaskData(msg)
    local liveId
    if type(msg) == "number" then
        liveId = msg
    else
        liveId = msg.livenessId
    end
    local data = this.getTaskLivenessBoxServerData(liveId);
    data.reward = -1;
    local taskBoxConfig = this.getTaskBoxTableData(tostring(liveId));
    if next(taskBoxConfig) ~= nil then
        --任务宝箱领取后
        local _boxDic = {}
        _boxDic.box_id = tostring(taskBoxConfig.f_BoxID)
        _boxDic.box_type = tostring(taskBoxConfig.f_BoxType)
        TAManager.TrackByDictionary("task_box_get", _boxDic)

        --local rewards = {};
        --local prizeTable = decodeJsonStrToTabel(taskBoxConfig.f_BoxAward);
        --local buffItems = logicMgr.EcoBuffManager.getEcoBuffByTypeAndItemId(Config.EcoBuffCondition.TaskAchieveBox, taskBoxConfig.f_BoxID);
        --if buffItems == 0 then
        --    buffItems = {}
        --end
        --for k, v in pairs(prizeTable) do
        --    local itemData = logicMgr.CostManager.getItemOrEquipDataByIdAndNum(v[1], v[2]);
        --    if itemData ~= nil then
        --        table.insert(rewards, itemData);
        --    end
        --end
        --for k, v in pairs(buffItems) do
        --    local itemData = logicMgr.CostManager.getItemOrEquipDataByIdAndNum(v[1], v[2]);
        --    if itemData ~= nil then
        --        table.insert(rewards, itemData);
        --    end
        --end
    end
    if type(msg) ~= "number" and #msg.items > 0 then
        showUI(PanelNames.UICommonItemGet, nil, nil, 3, msg.items);
    end
end

-- function TaskManager.updataAllSevemChallengeBoxServerData(serverData)
--     for i = 1, #serverData do
--         this.updataOneSevemChallengeBoxServerData(serverData[i]);
--     end
-- end

-- function TaskManager.updataOneSevemChallengeBoxServerData(singletask)
--     local data = this.getTaskLivenessBoxServerData(singletask.livenessBoxId);
--     data["livenessBoxId"] = singletask.livenessBoxId;
--     if(singletask.reward == 1)then
--         singletask.reward = -1
--     end
--     data["reward"] = singletask.reward;
--     local tempTaskConfig = NewcomerTaskBoxData[tostring(singletask.livenessBoxId)];
--     if next(tempTaskConfig) ~= nil then
--         if singletask.reward ~= -1 then
--             if this.getTaskLivenessServerData("6").liveness >= tempTaskConfig.f_NeedExpCount then
--                 data["reward"] = 1
--             end
--         end
--     else
--         logError("找不到该任务宝箱t_newcomertaskbox id:"..tostring(singletask.livenessBoxId))
--     end
-- end

-- function TaskManager.updateGetSevemChallengeRewardsServerTaskData(msg)
--     local data = this.getTaskLivenessBoxServerData(msg.awardID);
--     data.reward = -1;
--     local taskBoxConfig = NewcomerTaskBoxData[tostring(msg.awardID)];
--     if next(taskBoxConfig) ~= nil then
--         --任务宝箱领取后
--         local _boxDic = {}
--         _boxDic.box_id = tostring(taskBoxConfig.f_BoxID)
--         _boxDic.box_type = tostring(taskBoxConfig.f_BoxType)
--         TAManager.TrackByDictionary("task_box_get", _boxDic)
--         local rewards = {};
--         local prizeTable = decodeJsonStrToTabel(taskBoxConfig.f_BoxAward);
--         for k, v in pairs(prizeTable) do
--             local itemData = logicMgr.CostManager.getItemOrEquipDataByIdAndNum(v[1], v[2]);
--             if itemData ~= nil then
--                 table.insert(rewards, itemData);
--             end
--         end
--         if #rewards > 0 then
--             showUI(PanelNames.UICommonItemGet, nil, nil, 3, rewards);
--         end
--     end
-- end

function TaskManager.getTaskLivenessServerData(id)
    if id == nil then
        return taskLivenessServerData;
    end
    local tempLiveness = taskLivenessServerData[tostring(id)];
    if tempLiveness == nil then
        tempLiveness = {};
        tempLiveness["livenessId"] = tonumber(id);
        tempLiveness["liveness"] = 0;
        taskLivenessServerData[tostring(id)] = tempLiveness;
    end
    return tempLiveness;
end

function TaskManager.getTaskLivenessBoxServerData(id)
    if id == nil then
        return taskLivenessBoxServerData;
    end
    local tempLiveness = taskLivenessBoxServerData[tostring(id)];
    if tempLiveness == nil then
        tempLiveness = {};
        tempLiveness["livenessBoxId"] = tonumber(id);
        tempLiveness["reward"] = 0;
        taskLivenessBoxServerData[tostring(id)] = tempLiveness;
    end
    return tempLiveness;
end

function TaskManager.getTaskServerDataByType(type)
    local serverData = this.getTaskServerData();
    local data = {};
    for k, v in pairs(serverData) do
        local tableData = this.getTaskTableData(v.taskId);
        if tableData.f_FunctionType == type then
            table.insert(data, v);
        end
    end
    return data;

end

--- 根据任务类型获取任务当前进度
---@param type number 任务类型
---@return number 任务进度
function TaskManager.getProgressByType(type)
    local serverData = this.getTaskServerData()
    local taskData
    for k, v in pairs(serverData) do
        local tableData = this.getTaskTableData(v.taskId)
        if tableData.f_TaskType == type then
            taskData = v
            break
        end
    end

    if taskData == nil then
        return 0
    end
    return taskData.progress or 0
end

function TaskManager.getTaskServerDataById(id)
    return taskServerData[tostring(id)]
end
function TaskManager.getTaskServerData(id)
    if id == nil then
        return taskServerData;
    end
    return taskServerData[tostring(id)] or {};
    --local tempProgress = taskServerData[tostring(id)];
    --local tempTaskConfig = this.getTaskTableData(id);
    --if tempProgress == nil then
    --    tempProgress = {};
    --    tempProgress["taskId"] = tonumber(id);
    --    tempProgress["progress"] = 0;
    --    tempProgress["status"] = 0;
    --    tempProgress["order"] = tempTaskConfig.f_Order;
    --    local flag = this.conditionAndJudge(decodeJsonStrToTabel(tempTaskConfig.f_Condition));
    --    if not flag then
    --        tempProgress["status"]= -0.5;
    --    end
    --    taskServerData[tostring(id)] = tempProgress;
    --else
    --    if tempProgress["status"] == -0.5 and this.conditionAndJudge(decodeJsonStrToTabel(tempTaskConfig.f_Condition)) then
    --        tempProgress["status"]= 0;
    --    end
    --end
    --return tempProgress;
end

function TaskManager.addOneReceivedByRemark(config)
    if this.taskReceivedByRemark[tostring(config.f_Remark)] == nil then
        this.taskReceivedByRemark[tostring(config.f_Remark)] = 0;
    end
    this.taskReceivedByRemark[tostring(config.f_Remark)] = this.taskReceivedByRemark[tostring(config.f_Remark)] + 1;
end

function TaskManager.getTaskReceivedByRemark(type)
    if this.taskReceivedByRemark[tostring(type)] == nil then
        this.taskReceivedByRemark[tostring(type)] = 0;
    end
    return this.taskReceivedByRemark[tostring(type)];
end
---------------------------------处理服务器数据----------结束-------------
---条件and判断
---返回，可行不可行，和不可行的第一个限制下标
function TaskManager.conditionAndJudge(must)
    this.condition[1] = logicMgr.HeroManager.GetRoleLevel();
    this.condition[2] = logicMgr.MapManager.getMapId();
    this.condition[3] = logicMgr.VipManager.getVipLevel();
    if must == nil or next(must) == nil then
        return true;
    end
    if this.condition == nil or next(this.condition) == nil then
        return false, 1;
    end
    for k, v in pairs(must) do
        if this.condition[v[1]] == nil or this.condition[v[1]] < v[2] then
            return false, k;
        end
    end
    return true;
end

function TaskManager.showTaskRewardByIdFromTable(id,isShow)
    local taskCg = this.getTaskTableData(id);
    local rewards = {};
    if taskCg.f_Award ~= "" then
        local prizeTable = decodeJsonStrToTabel(taskCg.f_Award);
        for k, v in pairs(prizeTable) do
            local itemData = logicMgr.CostManager.getItemOrEquipDataByIdAndNum(v[1], v[2]);
            if itemData ~= nil then
                table.insert(rewards, itemData);
            end
        end
    end
    if taskCg.f_ExpCount > 0 then
        local iconId;
        if taskCg.f_ExpType == EnumConst.TaskType.dailyTask then
            iconId = EnumConst.TaskExpIconShowId.DayTask;
        elseif taskCg.f_ExpType == EnumConst.TaskType.weekTask then
            iconId = EnumConst.TaskExpIconShowId.WeekTask;
        elseif taskCg.f_ExpType == EnumConst.TaskType.achievementTask then
            iconId = EnumConst.TaskExpIconShowId.AchieveTask;
        elseif taskCg.f_ExpType == EnumConst.TaskType.sevenChallengeTask then
            iconId = EnumConst.TaskExpIconShowId.SevenChallengeTask;
        end
        if iconId ~= nil then
            local itemData = logicMgr.CostManager.getItemOrEquipDataByIdAndNum(iconId, taskCg.f_ExpCount);
            if itemData ~= nil then
                table.insert(rewards, itemData);
            end
        end
    end
    if #rewards > 0 then
        if taskCg.f_Remark == EnumConst.AchieveTaskType.Chapter and taskCg.f_FunctionType == EnumConst.TaskType.achievementTask then
            showUI(PanelNames.UICommonItemGet, nil, nil, 3, rewards,function()
                FireEvent(Config.EventType.ChapterTaskRewardGetDone)
            end);
        else
            if taskCg.f_Remark == EnumConst.AchieveTaskType.Custom and taskCg.f_FunctionType == EnumConst.TaskType.achievementTask then
                FireEvent(Config.EventType.UIBattleChapterRewardSuc,id,rewards)
                --showUI(PanelNames.UICommonItemGet, nil, nil, 3, rewards);
            elseif taskCg.f_FunctionType == EnumConst.TaskType.sevenChallengeTask then
                showUI(PanelNames.UICommonItemGet, nil, nil, 3, rewards);
            else
                if not isShow then
                    FireEvent(Config.EventType.TaskShowRewardAnim,id,rewards)
                end
            end
            --showUI(PanelNames.UICommonItemGet, nil, nil, 3, rewards);
        end

    end
end
--
--function TaskManager.getTaskTableDataByRemark(type)
--    type = tostring(type);
--    if this.taskTableDataByRemark[type] == nil then
--        this.taskTableDataByRemark[type] = {};
--        for k, v in pairs(this.getTaskTableDataByType(EnumConst.TaskType.achievementTask)) do
--            if v.f_Remark == tonumber(type) then
--                table.insert(this.taskTableDataByRemark[type], v);
--            end
--        end
--    end
--    return this.taskTableDataByRemark[type];
--end
--
--function TaskManager.getRemarkFristTableDataByType(type)
--    type = tostring(type);
--    if taskRemarkNowTableData[type] == nil then
--        taskRemarkNowTableData[type] = {};
--        for k, v in pairs(this.getTaskTableDataByRemark(type)) do
--            if v.f_PreTaskId == 0 then
--                table.insert(taskRemarkNowTableData[type], v);
--            end
--        end
--    end
--    return taskRemarkNowTableData[type];
--end
function TaskManager.getChapterCfgList()
    local serverData = this.getTaskTableData();
    local data = {};
    local config;
    for k, v in pairs(serverData) do
        config = this.getTaskTableData(v.f_TaskId);
        if config.f_Remark == EnumConst.AchieveTaskType.Chapter and config.f_FunctionType == EnumConst.TaskType.achievementTask then
            table.insert(data, config);
        end
    end
    return data;
end
function TaskManager.getRemarkShowDataByType(type)
    local serverData = this.getTaskServerData();
    local data = {};
    local config;
    for k, v in pairs(serverData) do
        config = this.getTaskTableData(v.taskId);
        if config.f_Remark == type and config.f_FunctionType == EnumConst.TaskType.achievementTask then
            table.insert(data, config);
        end
    end
    return data;
end

function TaskManager.getTaskBoxTableData(id)
    if id == nil then
        return taskBoxTableData or {};
    end
    return taskBoxTableData[tostring(id)] or {};
end

function TaskManager.getTaskTableData(id)
    if id == nil then
        return taskTableData or {};
    end
    return taskTableData[tostring(id)] or {};
end
--
--function TaskManager.getTaskAllExpCountByType(type)
--    if this.taskAllExpCountByType[tostring(type)] == nil then
--        this.getTaskTableDataByType(type);
--    end
--    return this.taskAllExpCountByType[tostring(type)] or 0;
--end
--
--function TaskManager.getTaskTableDataByType(type)
--    if this.taskTableDataByType[tostring(type)] == nil then
--        this.taskAllExpCountByType[tostring(type)] = 0;
--        local tableData = this.getTaskTableData();
--        local data = {};
--        for k, v in pairs(tableData) do
--            if v.f_FunctionType == type then
--                this.taskAllExpCountByType[tostring(type)] = this.taskAllExpCountByType[tostring(type)] + v.f_ExpCount;
--                table.insert(data, v);
--            end
--        end
--        this.taskTableDataByType[tostring(type)] = data;
--    end
--    return this.taskTableDataByType[tostring(type)];
--end

function TaskManager.getTaskBoxByType(type)
    if this.taskBoxTableDataByType[tostring(type)] == nil then
        local tableData = this.getTaskBoxTableData();
        local data = {};
        for k, v in pairs(tableData) do
            if v.f_BoxType == type then
                table.insert(data, v);
            end
        end
        this.taskBoxTableDataByType[tostring(type)] = data;
    end
    return this.taskBoxTableDataByType[tostring(type)];
end
function TaskManager.initUnlockData()
    local cfg=G.dataTable["t_functionswitch"]
    this.unlockData={}
    for _,v in pairs(cfg)do
        if v.f_FunctionUnlock==1 then
            table.insert(this.unlockData,v)
        end
        if v.f_ShowStory==1 then
            table.insert(this.unlockStoryData,v)
        end
    end
    --table.sort(this.unlockData,function (a,b)
    --    return a.f_FunctionId<b.f_FunctionId
    --end)
end
function TaskManager.getUnlockData()
    table.sort(this.unlockData,function(a,b)
        if a.f_UnlockStage~=b.f_UnlockStage then
            return a.f_UnlockStage<b.f_UnlockStage
        else
            return a.f_FunctionId<b.f_FunctionId
        end
    end)
    return this.unlockData
end
function TaskManager.getUnlockStoryData()
    table.sort(this.unlockStoryData,function(a,b)
        if a.f_UnlockStage~=b.f_UnlockStage then
            return a.f_UnlockStage<b.f_UnlockStage
        else
            return a.f_FunctionId<b.f_FunctionId
        end
    end)
    return this.unlockStoryData
end

return TaskManager